package top.codedance.iotp.tools.terminal;

import top.codedance.iotp.common.util.SystemUtil;
import top.codedance.iotp.tools.terminal.ui.ShellFrame;
import top.codedance.iotp.client.Version;
import org.ini4j.Profile;
import org.ini4j.Wini;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TerminalApplication {
    public static final Long version = Long.valueOf(Version.VERSION);
    public static ExecutorService pool = Executors.newCachedThreadPool();
    public static Wini ini = null; //ini文件读取器
    private static final String CMD_TMP_FILENAME = "terminal_cms";
    private static final String LOG_FILENAME = "terminal.log";
    public static final List<Character> numbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
    public static final List<Character> hexNumbers = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F');

    public static void main(String[] args) {
        initIniConfig();
        updateSkin();
        java.awt.EventQueue.invokeLater(() -> new ShellFrame().setVisible(true));
    }

    private static void updateSkin(){
        String defaultFeel = "Nimbus";
        Map<String, Map<String, String>> settings = TerminalApplication.readConfig();
        if(settings.containsKey("ui")){
            Map<String, String> ui = settings.get("ui");
            if(ui.containsKey("skin")) {
                defaultFeel = ui.get("skin");
            }
        }
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if (defaultFeel.equals(info.getName())) {
                    syslogInfo("use skin " + info.getName());
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception ex) {
            syslogInfo("Run fail: " + ex.getMessage());
        }
    }

    /**
     * 读取ini配置文件
     */
    public static void initIniConfig() {
        String strDir = System.getProperty("user.home");
        String appDir = strDir + File.separatorChar + ".iot";
        String iniFilePath = appDir + File.separatorChar + "terminal_settings.ini";
        File f = new File(iniFilePath);
        if (f.exists()) {
            try {
                ini = new Wini(f);
            } catch (IOException e) {
                syslogInfo("Ini file configure fail: " + e.getMessage());
            }
        } else {
            try {
                File dir = f.getParentFile();
                if(!dir.exists()){
                    dir.mkdirs();
                }
                f.createNewFile();
                ini = new Wini(f);
            } catch (Exception e) {
                syslogInfo("Create ini file fail: "  + e.getMessage());
            }
        }
    }

    /**
     * 配置插件参数
     *
     * @param params
     * @throws Exception
     */
    public static void saveConfig(Map<String, Map<String, String>> params) throws Exception {
        Set<Map.Entry<String, Map<String, String>>> entries = params.entrySet();
        for (Map.Entry<String, Map<String, String>> item : entries) {
            String section = item.getKey();
            Map<String, String> subParams = item.getValue();
            Set<Map.Entry<String, String>> subEntries = subParams.entrySet();
            for (Map.Entry<String, String> subItem : subEntries) {
                ini.add(section, subItem.getKey(), subItem.getValue());
            }
        }
        ini.store();
    }

    /**
     * 读取插件参数
     *
     * @return
     */
    public static Map<String, Map<String, String>> readConfig() {
        Map<String, Map<String, String>> results = new HashMap<>();
        Set<Map.Entry<String, Profile.Section>> entries = ini.entrySet();
        String key;
        String subkey;
        for (Map.Entry<String, Profile.Section> item : entries) {
            key = item.getKey();
            Profile.Section section = item.getValue();
            Set<String> subKeys = section.keySet();
            Iterator<String> iterator = subKeys.iterator();
            Map<String, String> items = new HashMap<>();
            while (iterator.hasNext()) {
                subkey = iterator.next();
                items.put(subkey, section.get(subkey));
            }
            results.put(key, items);
        }
        return results;
    }
    
    /**
     * 读取命令帮助文本
     * @return 
     */
    public static ArrayList<String> readCmds(){
        return SystemUtil.readTempFileToList(CMD_TMP_FILENAME);
    }
    
    /**
     * 写入命令帮助文本
     * @param results 
     */
    public static void writeCmds(ArrayList<String> results){
        StringBuffer sb = new StringBuffer();
        for(String l : results){
            sb.append(l);
            sb.append('\r');
        }
        SystemUtil.genTempFile(CMD_TMP_FILENAME, sb.toString());
    }

    /**
     * 系统日志输出，任何情况下都打印
     *
     * @param info
     */
    public static void syslogInfo(String info) {
        System.out.println(info);
        appendLog(info);
    }

    /**
     * 增加日志
     * @param log
     */
    public static void appendLog(String log){
        StringBuilder sb = new StringBuilder();
        String s = readLog();
        if(!s.isEmpty()) {
            sb.append(s);
        }
        sb.append(log);
        writeLog(sb.toString());
    }

    /**
     * 写入日志
     * @param log
     */
    public static void writeLog(String log){
        SystemUtil.writeFile(SystemUtil.getProjectUserDirPath() + File.separatorChar + LOG_FILENAME, log);
    }

    /**
     * 读取日志
     * @return
     */
    public static String readLog(){
        return SystemUtil.readFile(SystemUtil.getProjectUserDirPath() + File.separatorChar + LOG_FILENAME);
    }
}
